Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rewrite all zeros(...) calls #25392

Closed
wants to merge 10 commits into from

Conversation

fredrikekre
Copy link
Member

This rewrites all zeros([T, ] dims...) calls, first commit is #25087

See JuliaLang/LinearAlgebra.jl#484, #24595, #25087

@fredrikekre
Copy link
Member Author

One interesting thing that I encountered while doing this transformation is the difficulty to understand calls like zeros(A, B) -- you have no idea if it is a Vector{A} of length B or if it is a Matrix{Float64} with size A × B. In here there was even calls like zeros(T, n) which I naturally thought was a Vector{T}, but turned out that in that context T was just an integer...

Therefore; I think we should consider doing one of the following:

  • @deprecate zeros(::Type{T}, dims...) fill(T(0), dims...) i.e. make zeros always return Float64
  • @deprecate zeros(dims...) zeros(Float64, dims...) i.e. require the first argument to be a type

@ararslan
Copy link
Member

ararslan commented Jan 4, 2018

+1 for requiring the first argument to be a type.

@@ -159,7 +159,7 @@
N = 10
p = 0.5
A = N*I + sprand(N, N, p)
X = zeros(Complex{Float64}, N, N)
X = fill(0.0+im, N, N)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not a complex zero.

@@ -1156,7 +1156,7 @@ the other elements are left untouched.
```jldoctest
julia> x = [1., 0., 3., 0., 5.];

julia> y = zeros(7);
julia> y = Vector{Float64}(uninitialized, 7);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The example is meant to show the last two zeros being preserved, so filling with uninitialized doesn't seem right.

@ggggggggg
Copy link
Contributor

What about something like this, so it is really obvious where the type should go?

julia> struct Zeros{T} end

julia> function (::Type{Zeros{T}})(n...) where T
       zeros(T,n...)
       end

julia> Zeros{Int}(4,5)
4×5 Array{Int64,2}:
 0  0  0  0  0
 0  0  0  0  0
 0  0  0  0  0
 0  0  0  0  0

@JeffBezanson
Copy link
Member

Triage likes zeros. Since zero is a globally-reasonable default for initializing arrays, it makes sense to draw the line at having a special function for zeros, and using fill for everything else.

@fredrikekre
Copy link
Member Author

Rebased and regrouped the commits: The first commit removes all calls to zeros where the value 0 is not special, and where something else is better to use. The second commit rewrites all zeros(dims) calls (i.e. calls withouth a type specified) and then follows a number of commits where we use literal 0's in combination with fill. Those rewrites typically results in less code. The last commit rewrites zeros(T, dims) to fill(zero(T), dims) which typically becomes a little bit longer, and gives a taste of a post zeros world.

If we decide to keep zeros (which it looks like we will) then I will drop the last commit, and then submit a follow up PR with deprecation of zeros(dims) to zeros(Float64, dims).

@@ -10,7 +10,7 @@ general nonsymmetric matrices respectively.

For the single matrix version,

`eigs(A; nev=6, ncv=max(20,2*nev+1), which=:LM, tol=0.0, maxiter=300, sigma=nothing, ritzvec=true, v0=zeros((0,))) -> (d,[v,],nconv,niter,nmult,resid)`
`eigs(A; nev=6, ncv=max(20,2*nev+1), which=:LM, tol=0.0, maxiter=300, sigma=nothing, ritzvec=true, v0=[]) -> (d,[v,],nconv,niter,nmult,resid)`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case preservation of the element type matters in this case, Float64[]? :)

@@ -125,7 +125,7 @@ julia> λ

For the two-input generalized eigensolution version,

`eigs(A, B; nev=6, ncv=max(20,2*nev+1), which=:LM, tol=0.0, maxiter=300, sigma=nothing, ritzvec=true, v0=zeros((0,))) -> (d,[v,],nconv,niter,nmult,resid)`
`eigs(A, B; nev=6, ncv=max(20,2*nev+1), which=:LM, tol=0.0, maxiter=300, sigma=nothing, ritzvec=true, v0=[]) -> (d,[v,],nconv,niter,nmult,resid)`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likewise here, in case preservation of the element type matters in this case, Float64[]? :)

@@ -17,7 +17,7 @@ using .ARPACK

## eigs
"""
eigs(A; nev=6, ncv=max(20,2*nev+1), which=:LM, tol=0.0, maxiter=300, sigma=nothing, ritzvec=true, v0=zeros((0,))) -> (d,[v,],nconv,niter,nmult,resid)
eigs(A; nev=6, ncv=max(20,2*nev+1), which=:LM, tol=0.0, maxiter=300, sigma=nothing, ritzvec=true, v0=[]) -> (d,[v,],nconv,niter,nmult,resid)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Likewise here the Float64[] question.)

@@ -57,15 +57,15 @@ function eigs(A::AbstractMatrix, B::AbstractMatrix; kwargs...)
eigs(convert(AbstractMatrix{Tnew}, A), convert(AbstractMatrix{Tnew}, B); kwargs...)
end
"""
eigs(A, B; nev=6, ncv=max(20,2*nev+1), which=:LM, tol=0.0, maxiter=300, sigma=nothing, ritzvec=true, v0=zeros((0,))) -> (d,[v,],nconv,niter,nmult,resid)
eigs(A, B; nev=6, ncv=max(20,2*nev+1), which=:LM, tol=0.0, maxiter=300, sigma=nothing, ritzvec=true, v0=[]) -> (d,[v,],nconv,niter,nmult,resid)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Likewise here the Float64[] question.)

@@ -246,7 +246,7 @@ function svds(A::AbstractMatrix{T}; kwargs...) where T
end

"""
svds(A; nsv=6, ritzvec=true, tol=0.0, maxiter=1000, ncv=2*nsv, v0=zeros((0,))) -> (SVD([left_sv,] s, [right_sv,]), nconv, niter, nmult, resid)
svds(A; nsv=6, ritzvec=true, tol=0.0, maxiter=1000, ncv=2*nsv, v0=[]) -> (SVD([left_sv,] s, [right_sv,]), nconv, niter, nmult, resid)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Likewise here the Float64[] question.)

@test_throws DimensionMismatch LinAlg.checksquare(zeros(2,3))
A2x2, A3x3, A2x3 = Matrix{Float64}.(uninitialized, ((2,2), (3,3), (2,3)))
@test LinAlg.checksquare(A2x2) == 2
@test LinAlg.checksquare(zA2x2, A3x3) == [2, 3]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

zA2x2 -> A2x2? :)


@test_throws DimensionMismatch LAPACK.orghr!(1, 10, C, zeros(elty,11))
@test_throws DimensionMismatch LAPACK.orghr!(1, 10, A10x10, x11)
end
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Beautifully done rewriting this section :).

@@ -15,12 +15,13 @@ using Base.LinAlg: mul!
((0,0), (0,4), (0,4)),
((3,0), (0,0), (3,0)),
((0,0), (0,0), (0,0)) )
@test Matrix{Float64}(uninitialized, dimsA) * Matrix{Float64}(uninitialized, dimsB) == zeros(dimsC)
A, B, C = Matrix{Float64}.(uninitialized, (dimsA, dimsB, dimsC))
@test A * B == C
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will the ((3,0), (0,4), (3,4)) case not fail?

A = Matrix{Float64}(uninitialized, 5, 0)
B = Matrix{ComplexF64}(uninitialized, 5, 0)
@test A'A == B'B == fill(0, (0,0))
@test A*A' == B*B' == fill(0, (5,5))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nicely done :).

b = eltya == Int ? rand(1:7, n, n) : convert(Matrix{eltya}, eltya <: Complex ? complex.(b, zeros(n,n)) : b)
x = eltya == Int ? rand(1:7, n) : copy!(Vector{eltya}(uninitialized, n), randn(n))
y = eltya == Int ? rand(1:7, n) : copy!(Vector{eltya}(uninitialized, n), randn(n))
b = eltya == Int ? rand(1:7, n, n) : copy!(Matrix{eltya}(uninitialized, n, n), randn(n,n)/2)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would simpler convert(Vector{eltya}, randn(n))-like rewrites work? :)

@@ -20,7 +20,7 @@ julia> A = [3+2im 9+2im; 8+7im 4+6im]
3+2im 9+2im
8+7im 4+6im

julia> B = zeros(Complex{Int64}, 2, 2)
julia> B = [0+0im 0+0im; 0+0im 0+0im]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0im suffices? :)

@@ -13,7 +13,7 @@ if Sys.iswindows()
if len == 0
return Libc.GetLastError() != ERROR_ENVVAR_NOT_FOUND ? "" : onError(str)
end
val = zeros(UInt16,len)
val = fill(zero(UInt16), len)
Copy link
Member

@Sacha0 Sacha0 Jan 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Slightly simpler: UInt16(0). (Edit: Likewise below with a number of different concrete types.)

@Sacha0
Copy link
Member

Sacha0 commented Jan 16, 2018

An appreciable fraction of the first commit's rewrites seem like strict improvements; merging those rewrites would be lovely independent of zeros remaining around.

Though more subjective, I also find most rewrites in commits three through nine improvements; merging some agreeable subset of those rewrites would be lovely independent of zeros remaining around as well.

Much thanks for your efforts on this front @fredrikekre! :)

@vtjnash
Copy link
Member

vtjnash commented May 29, 2021

Were you still interested in doing the changes suggested by Sacha0, or should we close this?

@KristofferC
Copy link
Member

Since zeros was kept I think this can be closed.

@KristofferC KristofferC closed this May 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants